﻿using nhCore.nMessage;
using System.Diagnostics;

namespace nhCore.Server;

//声明一个方法型，关键字就是delegate,有参数就带上参数
public delegate void AnalysisResult_EventHandler(IO sender, object values, Cmd cmd);

/// <summary>
/// 连接，Tcp中对应Client，串口通讯中对应COM口
/// </summary>
public class Conn
{
    public string HandshakeFrame {  get; set; }

    private readonly IO _io;

    /// <summary>
    /// 最后连接的客户端地址，串口为串口名，TcpClient为IP地址
    /// </summary>
    private readonly string _clientAddress;

    /// <summary>
    /// 为flase时停止对应task
    /// </summary>
    private bool _isRunning = true;

    /// <summary>
    /// 本连接下的命令列表
    /// </summary>
    public List<Cmd> Cmds { get; set; } =[];

    private readonly object _client;

    private AnalysisResult_EventHandler AnalysisResult { get; set; }

    public Conn(IO io, object client, AnalysisResult_EventHandler analysisResult, string handshakeFrame)
    {
        _io = io;
        _client = client;
        AnalysisResult = analysisResult;
        HandshakeFrame = handshakeFrame;

        string str;
        if (client is System.IO.Ports.SerialPort serialPort)
        {
            _clientAddress = serialPort.PortName;
            str = $"{_clientAddress}接口已打开。";
        }
        else if (client is System.Net.Sockets.TcpClient tcpClient)
        {
            if (tcpClient.Client.RemoteEndPoint is System.Net.IPEndPoint iPEndPoint)
            {
                _clientAddress = (iPEndPoint.Address.ToString() +
                    ":" + iPEndPoint.Port.ToString());
                str = $"客户端[{_clientAddress}]已连接。握手帧[{handshakeFrame}]";
            }
            else
            {
                _clientAddress = "未知地址的Tcp连接";
                str = $"{_clientAddress}。";
            }
        }
        else
        {
            _clientAddress = "未知接口连接";
            str = $"{_clientAddress}。";
        }
        NMessage.Message(str);

        Task task = Task.Factory.StartNew(CmdTask);
    }

    private void CmdTask()
    {
        while (_isRunning)
        {
            if (Cmds.Count == 0)
            {
                NMessage.Error($"【{HandshakeFrame}】对应的命令帧为0。");
                return;
            }

            Cmd TmpCmd = Cmds.OrderBy(x => x.Time).First();//没设备时会为空
            int sleepTime = (int)(TmpCmd.Time - DateTime.Now).TotalMilliseconds;//计算最近命令休眠相应时间

            if (sleepTime <= 0) //立即发送
            {
                Debug.WriteLine($"立即发送{TmpCmd.SentCmd.Key}");
                object oRead = _io.SendAccept(_client, TmpCmd.SentCmd.GetCmd());//调用函数立即发送

                if (TmpCmd.SentCmd.IsAnswer(oRead))//效验通过，功能码、地址符合
                {
                    Debug.WriteLine($"\t\t有回复：{TmpCmd.SentCmd.Key}");
                    TmpCmd.SentCmd.SleepState = false;
                    TmpCmd.FailedCount = 0;
                    object o = TmpCmd.SentCmd.Analyzer.Analysis(oRead);//解析
                    AnalysisResult(_io, o, TmpCmd);//解析结果处理

                    TmpCmd.SentCmd.NextCmd();//实时类用继承基类的空方法
                }
                else
                {   //无回复或回复异常
                    TmpCmd.FailedCount++;
                    Debug.WriteLine($"{_clientAddress}接口中 <{TmpCmd.SentCmd.Key}> {TmpCmd.FailedCount}次失败。");
                    if (TmpCmd.FailedCount >= 3)
                    {
                        if (TmpCmd.SentCmd.Automatic)
                        {
                            TmpCmd.SentCmd.SleepState = true;//自动命令进入SleepState
                            Debug.WriteLine("暂缓发送");
                        }
                        else
                        {
                            TmpCmd.IsDelete = true;
                            NMessage.Warn($"{_clientAddress}接口中 <{TmpCmd.SentCmd.Key}> {TmpCmd.FailedCount}次失败，不再发送");
                            Debug.WriteLine("不再发送");
                        }
                    }
                }

                if (TmpCmd.IsDelete) //非Auto命令发送3次失败或任务完成即删除
                {
                    _ = Cmds.Remove(TmpCmd);
                    if (Cmds.Count == 0)
                    {
                        _isRunning = false;
                    }
                }
                else
                {
                    Debug.WriteLine($"下一条命令:{TmpCmd.SentCmd.Key},OffSet:{TmpCmd.SentCmd.OffSet},间隔:{TmpCmd.SentCmd.DelayTime}ms");
                    TmpCmd.RefreshTime();
                }
            }
            else
            {   //休眠
                Debug.WriteLine($"休眠时间：{sleepTime}ms");
                Thread.Sleep(sleepTime);
            }
        }
    }
}